﻿using Nop.Admin.Models.Stores;
using Nop.Core;
using Nop.Core.Domain.Common;
using Nop.Core.Domain.Customers;
using Nop.Core.Domain.Directory;
using Nop.Core.Domain.Stores;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Customers;
using Nop.Services.Directory;
using Nop.Services.ExportImport;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Services.Security;
using Nop.Services.Stores;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Telerik.Web.Mvc;

namespace Nop.Admin.Controllers
{
    [AdminAuthorize]
    public partial class StoreController : BaseNopController
    {
        #region Fields

        private readonly ICategoryService _categoryService;
        private readonly IStoreService _storeService;
        private readonly IProductService _productService;
        private readonly ILanguageService _languageService;
        private readonly ILocalizationService _localizationService;
        private readonly ILocalizedEntityService _localizedEntityService;
        private readonly IExportManager _exportManager;
        private readonly IWorkContext _workContext;
        private readonly ICustomerActivityService _customerActivityService;
        private readonly IPermissionService _permissionService;
        private readonly AdminAreaSettings _adminAreaSettings;

        private readonly IBranchService _branchService;
        private readonly ICountryService _countryService;
        private readonly IStateProvinceService _stateProvinceService;
        private readonly ICustomerService _customerService;
        private readonly IRegionService _regionService;

        #endregion

        #region Constructors

        public StoreController(ICategoryService categoryService, IStoreService storeService,
            IProductService productService, ILanguageService languageService,
            ILocalizationService localizationService, ILocalizedEntityService localizedEntityService,
            IExportManager exportManager, IWorkContext workContext,
            ICustomerActivityService customerActivityService, IPermissionService permissionService,
            AdminAreaSettings adminAreaSettings, IBranchService branchService, ICountryService countryService,
            IStateProvinceService stateProvinceService, ICustomerService customerService,
            IRegionService regionService)
        {
            this._categoryService = categoryService;
            this._storeService = storeService;
            this._productService = productService;
            this._languageService = languageService;
            this._localizationService = localizationService;
            this._localizedEntityService = localizedEntityService;
            this._exportManager = exportManager;
            this._workContext = workContext;
            this._customerActivityService = customerActivityService;
            this._permissionService = permissionService;
            this._adminAreaSettings = adminAreaSettings;

            this._branchService = branchService;
            this._countryService = countryService;
            this._stateProvinceService = stateProvinceService;
            this._customerService = customerService;
            this._regionService = regionService;
        }

        #endregion

        #region Utilities

        [NonAction]
        public void UpdateLocales(Store store, StoreModel model)
        {
            foreach (var localized in model.Locales)
            {
                _localizedEntityService.SaveLocalizedValue(store,
                                                               x => x.Name,
                                                               localized.Name,
                                                               localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(store,
                                                           x => x.Description,
                                                           localized.Description,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(store,
                                                           x => x.MetaKeywords,
                                                           localized.MetaKeywords,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(store,
                                                           x => x.MetaDescription,
                                                           localized.MetaDescription,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(store,
                                                           x => x.MetaTitle,
                                                           localized.MetaTitle,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(store,
                                                           x => x.SeName,
                                                           localized.SeName,
                                                           localized.LanguageId);
            }
        }

        [NonAction]
        public void UpdateLocalesBranch(Branch branch, BranchModel model)
        {
            foreach (var localized in model.Locales)
            {
                _localizedEntityService.SaveLocalizedValue(branch,
                                                               x => x.Name,
                                                               localized.Name,
                                                               localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(branch,
                                                           x => x.City,
                                                           localized.City,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(branch,
                                                           x => x.Address1,
                                                           localized.Address1,
                                                           localized.LanguageId);

                _localizedEntityService.SaveLocalizedValue(branch,
                                                           x => x.Address2,
                                                           localized.Address2,
                                                           localized.LanguageId);
            }
        }

        #endregion

        #region List

        public ActionResult Index()
        {
            return RedirectToAction("List");
        }

        public ActionResult List()
        {
            int curManagedStoreId;
            bool isStoreAdmin, canManageAllStore, isAccessDenied;
            _permissionService.SecurityAccessForAll(out curManagedStoreId, out isStoreAdmin, out canManageAllStore, out isAccessDenied);
            if (isAccessDenied)
                return AccessDeniedView();

            if (curManagedStoreId != Store.AllStoreReservedId && !isStoreAdmin && !canManageAllStore)
                return RedirectToAction("Edit", new { id = curManagedStoreId });

            ViewBag.IsAdmin = curManagedStoreId == Store.AllStoreReservedId || canManageAllStore;

            return View();
        }

        [HttpPost, GridAction(EnableCustomBinding = true)]
        public ActionResult List(GridCommand command)
        {
            //Allow storeAdmin, Admin and store manager with authority of all store
            int curManagedStoreId;
            bool isStoreAdmin, canManageAllStore, isAccessDenied;
            _permissionService.SecurityAccessForAll(out curManagedStoreId, out isStoreAdmin, out canManageAllStore, out isAccessDenied);
            if (isAccessDenied)
                return Content("Access denied.");

            int adminCustomerId = canManageAllStore ? 0 : _workContext.CurrentCustomer.Id;
            var stores = _storeService.GetAllStores(command.Page - 1, command.PageSize, true, false, adminCustomerId);

            var gridModel = new GridModel<StoreModel>
            {
                Data = stores.Select(x => x.ToModel()),
                Total = stores.TotalCount
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        #endregion

        #region Create / Edit / Delete

        public ActionResult Create()
        {
            bool isStoreAdmin, canManageAllStore, isAccessDenied;
            _permissionService.SecurityAccessForStoreAdmin(out isStoreAdmin, out canManageAllStore, out isAccessDenied);
            if (isAccessDenied)
                return AccessDeniedView();

            var model = new StoreModel();
            //locales
            AddLocales(_languageService, model.Locales);
            //default values
            model.PageSize = 4;
            model.Published = false;
            model.Featured = false;
            model.BillToCustomerId = 0;
            model.IsStoreAdmin = true;

            //Need improvement without hard coding
            model.MonthlyCharge = 0;
            model.ServiceChargeRate = 0;
            model.StorageAmount = 0;
            model.IsAdmin = canManageAllStore;
            //region
            model.RegionCollection = _regionService.GetAllRegions();

            return View(model);
        }

        [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")]
        public ActionResult Create(StoreModel model, bool continueEditing)
        {
            bool isStoreAdmin, canManageAllStore, isAccessDenied;
            _permissionService.SecurityAccessForStoreAdmin(out isStoreAdmin, out canManageAllStore, out isAccessDenied);
            if (isAccessDenied)
                return AccessDeniedView();

            try
            {
                //decode description
                model.Description = HttpUtility.HtmlDecode(model.Description);
                foreach (var localized in model.Locales)
                    localized.Description = HttpUtility.HtmlDecode(localized.Description);

                if (ModelState.IsValid)
                {
                    var store = model.ToEntity();
                    store.Featured = false;
                    store.Published = false;
                    store.BillToCustomerId = _customerService.GetCustomerByEmail(model.CustomerEmail).Id;
                    var customer = _workContext.CurrentCustomer;
                    if (canManageAllStore)
                    {
                        store.MonthlyCharge = model.MonthlyCharge;
                        store.ServiceChargeRate = model.ServiceChargeRate;
                        store.StorageAmount = model.StorageAmount;
                        store.StorageChargeRate = model.StorageChargeRate;
                        store.TransactionProcessingChargeRate = model.TransactionProcessingChargeRate;
                        store.Featured = model.Featured;
                        store.Published = model.Published;
                    }

                    //assign store manage right
                    store.AdminCustomerId = customer.Id;
                    store.CreatedOnUtc = DateTime.UtcNow;
                    store.UpdatedOnUtc = DateTime.UtcNow;
                    _storeService.InsertStore(store);
                    //locales
                    UpdateLocales(store, model);

                    //activity log
                    _customerActivityService.InsertActivity("AddNewStore", _localizationService.GetResource("ActivityLog.AddNewStore"), store.Name);

                    SuccessNotification(_localizationService.GetResource("Admin.Catalog.Stores.Added"));
                    return continueEditing ? RedirectToAction("Edit", new { id = store.Id }) : RedirectToAction("List");
                }
            }
            catch (Exception exc)
            {
                ErrorNotification(exc);
            }

            //if sth failed reload the page
            //locales
            AddLocales(_languageService, model.Locales);
            //default values
            model.PageSize = 4;
            model.Published = true;
            model.Featured = false;
            model.BillToCustomerId = 0;
            model.IsStoreAdmin = true;

            //Need improvement without hard coding
            model.MonthlyCharge = 0;
            model.ServiceChargeRate = 0;
            model.StorageAmount = 0;
            model.IsAdmin = false;
            if (canManageAllStore)
                model.IsAdmin = true;
            return View(model);
        }

        public ActionResult Edit(int id)
        {
            var currentCustomer = _workContext.CurrentCustomer;
            int curManagedStoreId;
            bool isStoreAdmin, canManageAllStore, isAccessDenied;
            _permissionService.SecurityAccessForAll(out curManagedStoreId, out isStoreAdmin, out canManageAllStore, out isAccessDenied);
            if (isAccessDenied)
                return AccessDeniedView();

            var store = id == Store.AllStoreReservedId ? null : _storeService.GetStoreById(id);
            if (store == null || store.Deleted)
            {
                //No store found with the specified id or accessing the reserved store ID
                ErrorNotification("Admin.Store.Common.NoStoreExist");
                return RedirectToAction("Index", "Home");
            }

            try
            {
                var model = store.ToModel();
                model.IsAdmin = canManageAllStore;
                model.IsStoreAdmin = isStoreAdmin;
                if (!canManageAllStore)
                {
                    if (store.AdminCustomerId != currentCustomer.Id && curManagedStoreId != id)
                    {
                        return AccessDeniedView();
                    }
                }
                //locales
                AddLocales(_languageService, model.Locales, (locale, languageId) =>
                {
                    locale.Name = store.GetLocalized(x => x.Name, languageId, false, false);
                    locale.Description = store.GetLocalized(x => x.Description, languageId, false, false);
                    locale.MetaKeywords = store.GetLocalized(x => x.MetaKeywords, languageId, false, false);
                    locale.MetaDescription = store.GetLocalized(x => x.MetaDescription, languageId, false, false);
                    locale.MetaTitle = store.GetLocalized(x => x.MetaTitle, languageId, false, false);
                    locale.SeName = store.GetLocalized(x => x.SeName, languageId, false, false);
                });

                var customer = _customerService.GetCustomerById(model.BillToCustomerId);
                if (customer != null)
                    model.CustomerEmail = customer.Email;
                //regions
                model.RegionCollection = _regionService.GetAllRegions();

                return View(model);
            }
            catch (Exception exc)
            {
                ErrorNotification(exc);
            }

            //if fail due to some reason
            return RedirectToAction("Index", "Home");
        }

        [HttpPost, ParameterBasedOnFormNameAttribute("save-continue", "continueEditing")]
        [FormValueRequired("save", "save-continue")]
        public ActionResult Edit(StoreModel model, bool continueEditing)
        {
            var customer = _workContext.CurrentCustomer;
            int curManagedStoreId;
            bool isStoreAdmin, canManageAllStore, isAccessDenied;
            _permissionService.SecurityAccessForAll(out curManagedStoreId, out isStoreAdmin, out canManageAllStore, out isAccessDenied);
            if (isAccessDenied)
                return AccessDeniedView();

            var store = model.Id == Store.AllStoreReservedId ? null : _storeService.GetStoreById(model.Id);
            if (store == null || store.Deleted)
            {
                //No store found with the specified id or accessing the reserved store ID
                ErrorNotification("Admin.Store.Edit.NoStoreExist");
                return RedirectToAction("Index", "Home");
            }
            if (!canManageAllStore)
            {
                if (store.AdminCustomerId != customer.Id && curManagedStoreId != model.Id)
                {
                    return AccessDeniedView();
                }
            }

            try
            {
                //decode description
                model.Description = HttpUtility.HtmlDecode(model.Description);
                foreach (var localized in model.Locales)
                    localized.Description = HttpUtility.HtmlDecode(localized.Description);

                if (ModelState.IsValid)
                {
                    //storeAdmin
                    if (isStoreAdmin)
                    {
                        store = model.ToEntity(store);
                        store.BillToCustomerId = _customerService.GetCustomerByEmail(model.CustomerEmail).Id;
                    }
                    else
                    {
                        store.Description = model.Description;
                    }
                    if (canManageAllStore)
                    {
                        store.AdminCustomerId = model.AdminCustomerId;
                        store.MonthlyCharge = model.MonthlyCharge;
                        store.ServiceChargeRate = model.ServiceChargeRate;
                        store.StorageAmount = model.StorageAmount;
                        store.StorageChargeRate = model.StorageChargeRate;
                        store.TransactionProcessingChargeRate = model.TransactionProcessingChargeRate;
                        store.Featured = model.Featured;
                        store.Published = model.Published;
                    }
                    store.UpdatedOnUtc = DateTime.UtcNow;
                    _storeService.UpdateStore(store);
                    //locales
                    UpdateLocales(store, model);
                    //delete homepage cache
                    RemoveCache();
                    //activity log
                    _customerActivityService.InsertActivity("EditStore", _localizationService.GetResource("Admin.ActivityLog.EditStore"), store.Name);

                    SuccessNotification(_localizationService.GetResource("Admin.Catalog.Stores.Updated"));
                    return continueEditing ? RedirectToAction("Edit", new { id = store.Id }) : RedirectToAction("List");
                }
            }
            catch (Exception exc)
            {
                ErrorNotification(exc);
            }

            //if fail due to some reason
            model.IsAdmin = false;
            if (canManageAllStore)
            {
                model.IsAdmin = true;
            }
            model.IsStoreAdmin = false;
            if (isStoreAdmin)
            {
                model.IsStoreAdmin = true;
            }
            //locales
            AddLocales(_languageService, model.Locales, (locale, languageId) =>
            {
                locale.Name = store.GetLocalized(x => x.Name, languageId, false, false);
                locale.Description = store.GetLocalized(x => x.Description, languageId, false, false);
                locale.MetaKeywords = store.GetLocalized(x => x.MetaKeywords, languageId, false, false);
                locale.MetaDescription = store.GetLocalized(x => x.MetaDescription, languageId, false, false);
                locale.MetaTitle = store.GetLocalized(x => x.MetaTitle, languageId, false, false);
                locale.SeName = store.GetLocalized(x => x.SeName, languageId, false, false);
            });
            return View(model);
        }

        [HttpPost]
        public ActionResult Delete(int id)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
                return AccessDeniedView();

            var store = _storeService.GetStoreById(id);
            if (store == null)
                //No store found with the specified id	
                return RedirectToAction("List");
            _storeService.DeleteStore(store);

            //delete products belongs to this store
            _productService.DeleteProductsByStore(id);
            //delete homepage cache
            RemoveCache();

            //activity log
            _customerActivityService.InsertActivity("DeleteStore", _localizationService.GetResource("ActivityLog.DeleteStore"), store.Name);

            SuccessNotification(_localizationService.GetResource("Admin.Catalog.Manufacturers.Deleted"));
            return RedirectToAction("List");
        }

        private void RemoveCache()
        {
            //delete homepage cache
            _productService.RemoveHomepageProductCache();
            _productService.RemoveBestSellersProductCache();
        }

        [HttpPost]
        public JsonResult StoreList(int storeId, int customerId)
        {
            //accountant should view all store
            bool canManageAllStore = _permissionService.Authorize(StandardPermissionProvider.ManageCatalog) || _permissionService.Authorize(StandardPermissionProvider.ManageOrders);
            int curManagedStoreId = canManageAllStore ? Store.AllStoreReservedId : _permissionService.GetAuthorizedStore(StandardPermissionProvider.ManageCatalog);
            bool isStoreAdmin = false;
            var storeSelectedList = new List<SelectListItem>();
            IList<Store> allStore = null;
            int adminCustomerId = 0;
            if (curManagedStoreId == 0)
            {
                //only work for storeAdmin
                adminCustomerId = canManageAllStore ? 0 : (customerId == 0 ? _workContext.CurrentCustomer.Id : customerId);
                allStore = _storeService.GetAllStores(true, true, adminCustomerId);
                isStoreAdmin = true;
            }
            else
            {
                allStore = _storeService.GetAllStores(true, true);
            }
            if (allStore == null || allStore.Count == 0)
            {
                return new JsonResult
                {
                    Data = new List<SelectListItem>()
                };
            }

            // Only show a single store
            if (curManagedStoreId != 1 && !canManageAllStore && !isStoreAdmin)
            {
                var store = _storeService.GetStoreById(curManagedStoreId);
                storeSelectedList.Add(new SelectListItem() { Text = store.Name, Value = store.Id.ToString() });
            }
            else
            {
                // Shows all stores which can be managed
                foreach (var s in allStore)
                    storeSelectedList.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString(), Selected = (s.Id == storeId) });
            }

            return new JsonResult
            {
                Data = storeSelectedList,
            };
        }

        public ActionResult MarkAsMainBranch(int branchid, int storeId)
        {
            var customer = _workContext.CurrentCustomer;
            bool isStoreAdmin, canManageAllStore, isAccessDenied;
            _permissionService.SecurityAccessForStoreAdmin(out isStoreAdmin, out canManageAllStore, out isAccessDenied);
            if (isAccessDenied)
                return AccessDeniedView();

            var store = _storeService.GetStoreById(storeId);
            if (store == null)
            {
                ErrorNotification(_localizationService.GetResource("Admin.Store.Common.NoStoreExist"));
                //No store found with the specified id	
                return RedirectToAction("List");
            }
            if (!canManageAllStore)
            {
                if (store.AdminCustomerId != customer.Id)
                {
                    return AccessDeniedView();
                }
            }

            store.MainBranchId = branchid;
            _storeService.UpdateStore(store);
            SuccessNotification(_localizationService.GetResource("Admin.Catalog.Store.MainBranch.Updated"));
            return RedirectToAction("Edit", new { id = store.Id });
        }
        #endregion

        #region Export / Import

        public ActionResult ExportXml()
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCatalog))
                return AccessDeniedView();

            try
            {
                int customerStoreId = (int)_workContext.CurrentCustomer.StoreId;
                var fileName = string.Format("stores_{0}.xml", DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
                var stores =
                    customerStoreId == Store.AllStoreReservedId ?
                    _storeService.GetAllStores(true) : new List<Store>() { _storeService.GetStoreById(customerStoreId) };
                var xml = _exportManager.ExportStoresToXml(stores);
                return new XmlDownloadResult(xml, fileName);
            }
            catch (Exception exc)
            {
                ErrorNotification(exc);
                return RedirectToAction("List");
            }
            //return null;
        }

        #endregion

        #region Braches

        [GridAction]
        public ActionResult BranchesSelect(int storeId, GridCommand command)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers)
                && !_permissionService.Authorize(StandardPermissionProvider.StoreAdmin))
                return Content("Access denied.");

            var store = _storeService.GetStoreById(storeId);
            if (store == null)
                return Content(_localizationService.GetResource("Admin.Store.Common.NoStoreExist"));
            var currentCustomer = _workContext.CurrentCustomer;
            if (!currentCustomer.IsAdmin() && store.AdminCustomerId != currentCustomer.Id)
            {
                //Validate storeAdmin
                return Content("Access denied.");
            }

            var branches = store.Branches.OrderByDescending(b => b.CreatedOnUtc).ThenByDescending(b => b.Id).ToList();
            var gridModel = new GridModel<BranchModel>
            {
                Data = branches.Select(x =>
                {
                    var model = x.ToModel();
                    model.IsMainBranch = (store.MainBranchId.HasValue && store.MainBranchId == x.Id) ? true : false;
                    if (x.Country != null)
                        model.CountryName = x.Country.Name;
                    if (x.StateProvince != null)
                        model.StateProvinceName = x.StateProvince.Name;
                    return model;
                }),
                Total = branches.Count
            };
            return new JsonResult
            {
                Data = gridModel
            };
        }

        [GridAction]
        public ActionResult BranchDelete(int storeId, int branchId, GridCommand command)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers)
                && !_permissionService.Authorize(StandardPermissionProvider.StoreAdmin))
                return Content("Access denied.");

            var store = _storeService.GetStoreById(storeId);
            if (store == null)
                throw new ArgumentException("No store found with the specified id", "storeId");
            var currentCustomer = _workContext.CurrentCustomer;
            if (!currentCustomer.IsAdmin() && store.AdminCustomerId != currentCustomer.Id)
            {
                //Validate storeAdmin
                return Content("Access denied.");
            }

            var branch = store.Branches.Where(b => b.Id == branchId).FirstOrDefault();
            // store.Branches.Remove(branch);
            // _storeService.UpdateStore(store);
            //now delete the address record

            _branchService.DeleteBranch(branch);

            return BranchesSelect(storeId, command);
        }

        public ActionResult BranchCreate(int storeId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers)
                 && !_permissionService.Authorize(StandardPermissionProvider.StoreAdmin))
                return AccessDeniedView();

            var store = _storeService.GetStoreById(storeId);
            if (store == null)
                ErrorNotification(_localizationService.GetResource("Admin.Store.Common.NoStoreExist"));
            var currentCustomer = _workContext.CurrentCustomer;
            if (!currentCustomer.IsAdmin() && store.AdminCustomerId != currentCustomer.Id)
            {
                //Validate storeAdmin
                return AccessDeniedView();
            }

            var model = new StoreBranchModel();
            model.Branch = new BranchModel();
            //locales
            AddLocales(_languageService, model.Branch.Locales);
            model.StoreId = storeId;
            //countries
            model.Branch.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.SelectCountry"), Value = "0" });
            foreach (var c in _countryService.GetAllCountries(true))
                model.Branch.AvailableCountries.Add(new SelectListItem() { Text = c.Name, Value = c.Id.ToString() });
            model.Branch.AvailableStates.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.OtherNonUS"), Value = "0" });

            return View(model);
        }

        [HttpPost]
        public ActionResult BranchCreate(StoreBranchModel model)
        {
            var customer = _workContext.CurrentCustomer;
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers)
                 && !_permissionService.Authorize(StandardPermissionProvider.StoreAdmin))
                return AccessDeniedView();

            var store = _storeService.GetStoreById(model.StoreId);
            if (store == null)
                ErrorNotification(_localizationService.GetResource("Admin.Store.Common.NoStoreExist"));
            if (!customer.IsAdmin() && store.AdminCustomerId != customer.Id)
            {
                //Validate storeAdmin
                return AccessDeniedView();
            }

            if (ModelState.IsValid)
            {
                var branch = model.Branch.ToEntity();
                branch.CreatedOnUtc = DateTime.UtcNow;
                //some validation
                if (branch.CountryId == 0)
                    branch.CountryId = null;
                if (branch.StateProvinceId == 0)
                    branch.StateProvinceId = null;
                store.Branches.Add(branch);
                _storeService.UpdateStore(store);

                //locales
                UpdateLocalesBranch(branch, model.Branch);

                SuccessNotification(_localizationService.GetResource("Admin.Catalog.Stores.Branches.Added"));
                return RedirectToAction("BranchEdit", new { branchId = branch.Id, storeId = model.StoreId });
            }

            //If we got this far, something failed, redisplay form
            model.StoreId = store.Id;
            //countries
            model.Branch.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.SelectCountry"), Value = "0" });
            foreach (var c in _countryService.GetAllCountries(true))
                model.Branch.AvailableCountries.Add(new SelectListItem() { Text = c.Name, Value = c.Id.ToString(), Selected = (c.Id == model.Branch.CountryId) });
            //states
            var states = model.Branch.CountryId.HasValue ? _stateProvinceService.GetStateProvincesByCountryId(model.Branch.CountryId.Value, true).ToList() : new List<StateProvince>();
            if (states.Count > 0)
            {
                foreach (var s in states)
                    model.Branch.AvailableStates.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString(), Selected = (s.Id == model.Branch.StateProvinceId) });
            }
            else
                model.Branch.AvailableStates.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.OtherNonUS"), Value = "0" });
            return View(model);
        }

        public ActionResult BranchEdit(int branchId, int storeId)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers)
                 && !_permissionService.Authorize(StandardPermissionProvider.StoreAdmin))
                return AccessDeniedView();

            var store = _storeService.GetStoreById(storeId);
            if (store == null)
                ErrorNotification(_localizationService.GetResource("Admin.Store.Common.NoStoreExist"));
            var currentCustomer = _workContext.CurrentCustomer;
            if (!currentCustomer.IsAdmin() && store.AdminCustomerId != currentCustomer.Id)
            {
                //Validate storeAdmin
                return AccessDeniedView();
            }

            var branch = _branchService.GetBranchById(branchId);
            if (branch == null)
                throw new ArgumentException("No branch found with the specified id", "branchId");

            var model = new StoreBranchModel();

            model.StoreId = storeId;
            model.Branch = branch.ToModel();
            //locales
            AddLocales(_languageService, model.Branch.Locales, (locale, languageId) =>
            {
                locale.Name = branch.GetLocalized(x => x.Name, languageId, false, false);
                locale.City = branch.GetLocalized(x => x.City, languageId, false, false);
                locale.Address1 = branch.GetLocalized(x => x.Address1, languageId, false, false);
                locale.Address2 = branch.GetLocalized(x => x.Address2, languageId, false, false);
            });
            //countries
            model.Branch.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.SelectCountry"), Value = "0" });
            foreach (var c in _countryService.GetAllCountries(true))
                model.Branch.AvailableCountries.Add(new SelectListItem() { Text = c.Name, Value = c.Id.ToString(), Selected = (c.Id == branch.CountryId) });
            //states
            var states = branch.Country != null ? _stateProvinceService.GetStateProvincesByCountryId(branch.Country.Id, true).ToList() : new List<StateProvince>();
            if (states.Count > 0)
            {
                foreach (var s in states)
                    model.Branch.AvailableStates.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString(), Selected = (s.Id == branch.StateProvinceId) });
            }
            else
                model.Branch.AvailableStates.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.OtherNonUS"), Value = "0" });

            return View(model);
        }

        [HttpPost]
        public ActionResult BranchEdit(StoreBranchModel model)
        {
            if (!_permissionService.Authorize(StandardPermissionProvider.ManageCustomers)
                 && !_permissionService.Authorize(StandardPermissionProvider.StoreAdmin))
                return AccessDeniedView();

            var store = _storeService.GetStoreById(model.StoreId);
            if (store == null)
                ErrorNotification(_localizationService.GetResource("Admin.Store.Common.NoStoreExist"));
            var currentCustomer = _workContext.CurrentCustomer;
            if (!currentCustomer.IsAdmin() && store.AdminCustomerId != currentCustomer.Id)
            {
                //Validate storeAdmin
                return AccessDeniedView();
            }

            var branch = _branchService.GetBranchById(model.Branch.Id);
            if (branch == null)
                throw new ArgumentException("No branch found with the specified id");

            if (ModelState.IsValid)
            {
                branch = model.Branch.ToEntity(branch);
                _branchService.UpdateBranch(branch);

                //locales
                UpdateLocalesBranch(branch, model.Branch);

                SuccessNotification(_localizationService.GetResource("Admin.Catalog.Stores.Branches.Updated"));
                return RedirectToAction("BranchEdit", new { branchId = model.Branch.Id, storeId = model.StoreId });
            }

            //If we got this far, something failed, redisplay form
            model.StoreId = store.Id;
            model.Branch = branch.ToModel();
            //countries
            model.Branch.AvailableCountries.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.SelectCountry"), Value = "0" });
            foreach (var c in _countryService.GetAllCountries(true))
                model.Branch.AvailableCountries.Add(new SelectListItem() { Text = c.Name, Value = c.Id.ToString(), Selected = (c.Id == branch.CountryId) });
            //states
            var states = branch.Country != null ? _stateProvinceService.GetStateProvincesByCountryId(branch.Country.Id, true).ToList() : new List<StateProvince>();
            if (states.Count > 0)
            {
                foreach (var s in states)
                    model.Branch.AvailableStates.Add(new SelectListItem() { Text = s.Name, Value = s.Id.ToString(), Selected = (s.Id == branch.StateProvinceId) });
            }
            else
                model.Branch.AvailableStates.Add(new SelectListItem() { Text = _localizationService.GetResource("Admin.Address.OtherNonUS"), Value = "0" });

            return View(model);
        }

        #endregion

    }
}
